home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / IPSUBR.C < prev    next >
Text File  |  1990-07-10  |  3KB  |  155 lines

  1. /* IP header and checksum processing
  2.  */
  3.  
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "internet.h"
  7. #include "timer.h"
  8. #include "netuser.h"
  9. #include "ip.h"
  10. /* Convert IP header in host format to network mbuf */
  11. struct mbuf *
  12. htonip(ip,data)
  13. struct ip *ip;
  14. struct mbuf *data;
  15. {
  16.     int16 hdr_len;
  17.     struct mbuf *bp;
  18.     register char *cp;
  19.     int16 checksum;
  20.  
  21.     hdr_len = IPLEN + ip->optlen;
  22.     if((bp = pushdown(data,hdr_len)) == NULLBUF){
  23.         free_p(data);
  24.         return NULLBUF;
  25.     }
  26.     cp = bp->data;
  27.  
  28.     *cp++ = (IPVERSION << 4) | (hdr_len >> 2);
  29.     *cp++ = ip->tos;
  30.     cp = put16(cp,ip->length);
  31.     cp = put16(cp,ip->id);
  32.     cp = put16(cp,ip->fl_offs);
  33.     *cp++ = ip->ttl;
  34.     *cp++ = ip->protocol;
  35.     cp = put16(cp,0);    /* Clear checksum */
  36.     cp = put32(cp,ip->source);
  37.     cp = put32(cp,ip->dest);
  38.     if(ip->optlen != 0)
  39.         memcpy(cp,ip->options,ip->optlen);
  40.  
  41.     /* Compute checksum and insert into header */
  42.     checksum = cksum(NULLHEADER,bp,hdr_len);
  43.     put16(&bp->data[10],checksum);
  44.  
  45.     return bp;
  46. }
  47. /* Extract an IP header from mbuf */
  48. int
  49. ntohip(ip,bpp)
  50. struct ip *ip;
  51. struct mbuf **bpp;
  52. {
  53.     int16 ihl;
  54.     char iphead[20];
  55.  
  56.     if(pullup(bpp,iphead,20) != 20)
  57.         return -1;
  58.  
  59.     if((ihl = (iphead[0] & 0xf) << 2) < IPLEN){
  60.         /* Bogus packet; header is too short */
  61.         return -1;
  62.     }
  63.     ip->version = (iphead[0] >> 4) & 0xf;
  64.     ip->tos = uchar(iphead[1]);
  65.     ip->length = get16(iphead + 2);
  66.     ip->id = get16(iphead + 4);
  67.     ip->fl_offs = get16(iphead + 6);
  68.     ip->ttl = uchar(iphead[8]);
  69.     ip->protocol = uchar(iphead[9]);
  70.     ip->source = get32(iphead + 12);
  71.     ip->dest = get32(iphead + 16);
  72.  
  73.     if((ip->optlen = ihl - IPLEN) != 0)
  74.         if (pullup(bpp,ip->options,ip->optlen) != ip->optlen)
  75.             return -1;
  76.  
  77.     return ip->optlen + IPLEN;
  78. }
  79. /* Perform end-around-carry adjustment */
  80. int16
  81. eac(sum)
  82. register int32 sum;    /* Carries in high order 16 bits */
  83. {
  84.     register int16 csum;
  85.  
  86.     while((csum = hiword(sum)) != 0)
  87.         sum = csum + (sum & 0xffffL);
  88.     return (int16) (sum & 0xffffl); /* Chops to 16 bits */
  89. }
  90. /* Checksum a mbuf chain, with optional pseudo-header */
  91. int16
  92. cksum(ph,m,len)
  93. struct pseudo_header *ph;
  94. register struct mbuf *m;
  95. int16 len;
  96. {
  97.     register unsigned int cnt, total;
  98.     register int32 sum, csum;
  99.     register char *up;
  100.     int16 csum1;
  101.     int swap = 0;
  102.     int16 lcsum();
  103.  
  104.     sum = 0l;
  105.  
  106.     /* Sum pseudo-header, if present */
  107.     if(ph != NULLHEADER){
  108.         sum = hiword(ph->source);
  109.         sum += loword(ph->source);
  110.         sum += hiword(ph->dest);
  111.         sum += loword(ph->dest);
  112.         sum += uchar(ph->protocol);
  113.         sum += ph->length;
  114.     }
  115.     /* Now do each mbuf on the chain */
  116.     for(total = 0; m != NULLBUF && total < len; m = m->next) {
  117.         cnt = min(m->cnt, len - total);
  118.         up = (char *)m->data;
  119.         csum = 0;
  120.  
  121.         if(((long)up) & 1){
  122.             /* Handle odd leading byte */
  123.             if(swap)
  124.                 csum = uchar(*up++);
  125.             else
  126.                 csum = (int16)(uchar(*up++) << 8);
  127.             cnt--;
  128.             swap = !swap;
  129.         }
  130.         if(cnt > 1){
  131.             /* Have the primitive checksumming routine do most of
  132.              * the work. At this point, up is guaranteed to be on
  133.              * a short boundary
  134.              */
  135.             csum1 = lcsum((unsigned short *)up, cnt >> 1);
  136.             if(swap)
  137.                 csum1 = (csum1 << 8) | (csum1 >> 8);
  138.             csum += csum1;
  139.         }
  140.         /* Handle odd trailing byte */
  141.         if(cnt & 1){
  142.             if(swap)
  143.                 csum += uchar(up[--cnt]);
  144.             else
  145.                 csum += (int16)(uchar(up[--cnt]) << 8);
  146.             swap = !swap;
  147.         }
  148.         sum += csum;
  149.         total += m->cnt;
  150.     }
  151.     /* Do final end-around carry, complement and return */
  152.     return ~eac(sum) & 0xffff;
  153. }
  154.  
  155. ə